package com.wz.service.impl;

import com.wz.config.Normal;
import com.wz.dao.BlockDao;
import com.wz.pojo.Block;
import com.wz.service.BlockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.response.EthBlockNumber;
import org.web3j.protocol.http.HttpService;
import rx.Subscription;

import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static org.web3j.protocol.core.DefaultBlockParameterName.EARLIEST;
import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST;

/**
 * @program: demo
 * @description:
 * @author: Wangzheng
 * @create: 2020-12-22 15:37
 **/
@Service
public class BlockServiceImpl implements BlockService {
	@Autowired
	private BlockService blockService;
	@Autowired
	private static Subscription subscription;
	@Autowired()
	private BlockDao blockDao;


	@Override
	public BigInteger findBigBlockNum() {
		Web3j web3j = Web3j.build(new HttpService(Normal.SERVER));
		EthBlockNumber send;
		try {
			send = web3j.ethBlockNumber().send();
			String result = send.getResult();

			BigInteger bigInteger = BigInteger.valueOf(Integer.parseInt(result.replaceAll("^0[x|X]", ""), 16));
			return bigInteger;
		} catch (IOException e) {
			System.out.println("异常信息" + " " + e);
		}
		return null;
	}

	@Override
	public HashMap<String, Object> getBlockResult() {
		//先定义一个map
		HashMap<String, Object> map = new HashMap<>();
		//调用service拿到块的最大编号
		BigInteger bigBlockNum = blockService.findBigBlockNum();
		//从最初,到最近的块 遍历
		for (int i = 1; i <= bigBlockNum.intValue(); i++) {
			subscription = Web3j.build(new HttpService(Normal.SERVER)).replayBlocksObservable(
					DefaultBlockParameter.valueOf(String.valueOf(EARLIEST)),
					DefaultBlockParameter.valueOf(String.valueOf(LATEST)),
					false).subscribe(ethBlock -> {
				//定义时间类型转换:		
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				//获取从块里拿到的时间戳:
				int time = ethBlock.getBlock().getTimestamp().intValue();
				//转换时间戳为具体日期时间:
				String timestamp = sdf.format(new Date(time * 1000L));
				//把初始的block数据写入map里面:
				BigInteger number = ethBlock.getBlock().getNumber();
				map.put("hash" + String.valueOf(number), ethBlock.getBlock().getHash());
				map.put("parentHash" + String.valueOf(number), ethBlock.getBlock().getParentHash());
				map.put("miner" + String.valueOf(number), ethBlock.getBlock().getMiner());
				map.put("difficulty" + String.valueOf(number), ethBlock.getBlock().getDifficulty());
				map.put("gasLimit" + String.valueOf(number), ethBlock.getBlock().getGasLimit());
				map.put("gasUsed" + String.valueOf(number), ethBlock.getBlock().getGasUsed());
				map.put("timestamp" + String.valueOf(number), timestamp);
				map.put("number" + String.valueOf(number), ethBlock.getBlock().getNumber());
				map.put("size" + String.valueOf(number), ethBlock.getBlock().getSize());
			});
		}
     return map;
	}

	@Override
	public HashMap<Integer, Block> getBlockDataToMap() {
		//调用service拿到最大块的编号:
		BigInteger bigBlockNum = blockService.findBigBlockNum();
		//定义此方法要返回的map对象 key为0-最大块的编号 value为Block pojo对象
		HashMap<Integer, Block> map1 = new HashMap<>();
		//调用service方法拿数据块的map 即将通过此map完成对Block实体的封装:
		HashMap<String, Object> map = blockService.getBlockResult();
		//循环遍历拿取map的key 同时new Block()对象把需要封装的对象添加进实体:
		for (int j = 0; j < bigBlockNum.intValue()+1; j++) {
			map1.put(Integer.valueOf(j),new Block()
					.setHash((String) map.get("hash" + j))
					.setParentHash((String) map.get("parentHash"+ j))
					.setMiner((String) map.get("miner"+j))
					.setDifficulty((BigInteger) map.get("difficulty"+j))
					.setGasLimit((BigInteger) map.get("gasLimit"+j))
					.setGasUsed((BigInteger) map.get("gasUsed"+j))
					.setTimestamp((String) map.get("timestamp"+j))
					.setNumber((BigInteger) map.get("number"+j))
					.setSize((BigInteger) map.get("size"+j)));
		}
		return map1;
	}

	@Override
	public String insertBlockData() {
		//调用service拿到我们封装好的带有Block对象的map
		HashMap<Integer, Block> map = blockService.getBlockDataToMap();
		//循环遍历map对象,拿到block对象
		for (Map.Entry<Integer, Block> entry : map.entrySet()) {
			Block block = entry.getValue();
			//调用dao的方法,插入数据库
			blockDao.insertBlock(block);
		}
		return null;
	}

	
	
	
	@Override
	public void insertDbData() {
		subscription = Web3j.build(new HttpService(Normal.SERVER)).replayBlocksObservable(
				DefaultBlockParameter.valueOf(String.valueOf(EARLIEST)),
				DefaultBlockParameter.valueOf(String.valueOf(LATEST)),
				false).subscribe(ethBlock -> {
			//定义时间类型转换:		
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			//获取从块里拿到的时间戳:
			int time = ethBlock.getBlock().getTimestamp().intValue();
			//转换时间戳为具体日期时间:
			String timestamp = sdf.format(new Date(time * 1000L));
			
			
			Block block = new Block();
				block
					.setNumber(ethBlock.getBlock().getNumber())
					.setHash(ethBlock.getBlock().getHash())
					.setParentHash(ethBlock.getBlock().getParentHash())
					.setMiner(ethBlock.getBlock().getMiner())
					.setDifficulty(ethBlock.getBlock().getDifficulty())
					.setGasLimit(ethBlock.getBlock().getGasLimit())
					.setGasUsed(ethBlock.getBlock().getGasUsed())
					.setTimestamp(timestamp)
					.setNumber(ethBlock.getBlock().getNumber())
					.setSize(ethBlock.getBlock().getSize());
			blockDao.insertBlock(block);
		});
	}
}
